package com.wyj.controller

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts
import com.hjq.toast.Toaster
import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager
import java.util.concurrent.locks.ReentrantLock

object UIController {
    interface IActivityLauncher {
        fun getCurrentContext(): Context?
        fun launch(intent: Intent, callback: ((resultCode: Int, data: Intent?) -> Unit)? = null)
    }

    private class ActivityLauncherImpl {
        private val launcherMap = hashMapOf<ActivityResultLauncher<Intent>, ((resultCode: Int, data: Intent?) -> Unit)?>()
        val lock = ReentrantLock()
        fun createActivityLauncher(getContext: () -> Context?, registerForActivityResult: (ActivityResultContract<Intent, ActivityResult>, ActivityResultCallback<ActivityResult>) -> ActivityResultLauncher<Intent>, maxLaunchSize: Int = 5): IActivityLauncher {
            repeat(maxLaunchSize) {
                var launcher: ActivityResultLauncher<Intent>? = null
                /*如果A同时打开B和C并接收回调，这个回调是在B、C都返回到A页面才执行的，并且是无序的，也许先执行C
                  所以不适用于A中for循环多次打开B，同时接收回调，一般也没这个需求*/
                launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult(), ActivityResultCallback { result ->
                    val mLauncher = launcher ?: return@ActivityResultCallback
                    lock.lock()
                    val callback = launcherMap[mLauncher]
                    launcherMap[mLauncher] = null
                    lock.unlock()
                    callback?.invoke(result.resultCode, result.data)
                })
                launcherMap[launcher] = null
            }
            return object : IActivityLauncher {
                override fun getCurrentContext(): Context? {
                    return getContext()
                }

                override fun launch(intent: Intent, callback: ((resultCode: Int, data: Intent?) -> Unit)?) {
                    lock.lock()
                    val launcher = launcherMap.entries.firstOrNull { it.value == null }?.key
                    if (launcher != null) {
                        launcherMap[launcher] = callback
                    }
                    lock.unlock()
                    launcher?.launch(intent)
                }
            }
        }
    }

    fun createActivityLauncher(getContext: () -> Context?, registerForActivityResult: (ActivityResultContract<Intent, ActivityResult>, ActivityResultCallback<ActivityResult>) -> ActivityResultLauncher<Intent>, maxLaunchSize: Int = 5): IActivityLauncher {
        return ActivityLauncherImpl().createActivityLauncher(getContext, registerForActivityResult, maxLaunchSize)
    }

    @JvmStatic
    fun startActivity(launcher: IActivityLauncher, cls: Class<*>, isFinishActivity: Boolean = false, callback: ((resultCode: Int, data: Intent?) -> Unit)? = null) {
        startActivity(launcher, cls, null, isFinishActivity, callback)
    }

    @JvmStatic
    @JvmOverloads
    fun startActivity(launcher: IActivityLauncher, cls: Class<*>, bundle: Bundle? = null, isFinishActivity: Boolean = false, callback: ((resultCode: Int, data: Intent?) -> Unit)? = null) {
        startActivity(launcher, Intent(launcher.getCurrentContext(), cls).apply { bundle?.let { this.putExtras(it) } }, isFinishActivity, callback)
    }

    @JvmStatic
    @JvmOverloads
    fun startActivity(launcher: IActivityLauncher, intent: Intent, isFinishActivity: Boolean = false, callback: ((resultCode: Int, data: Intent?) -> Unit)? = null) {
        val context = launcher.getCurrentContext() ?: return
        if (intent.resolveActivity(context.packageManager) == null) {
            Toaster.show("应用不可用")
            return
        }
        val canFinish = isFinishActivity && context is Activity && !context.isFinishing
        if (canFinish) {
            //手动调用ActivityManager，自动调用会有问题
            QMUISwipeBackActivityManager.getInstance().onActivityDestroyed(context as Activity)
        }
        launcher.launch(intent, callback)
        if (canFinish) {
            (context as Activity).finish();
        }
    }

    @JvmStatic
    fun callTel(launcher: IActivityLauncher, tel: String) {
        val intent = Intent(Intent.ACTION_DIAL);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.data = Uri.parse("tel:$tel");
        launcher.launch(Intent.createChooser(intent, "请选择"))
    }

    @JvmOverloads
    @JvmStatic
    fun toOtherApp(launcher: IActivityLauncher, uri: Uri, isFinishActivity: Boolean = false) {
        val intent = Intent(Intent.ACTION_VIEW)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.data = uri
        launcher.launch(Intent.createChooser(intent, "请选择"))
        val context = launcher.getCurrentContext()
        if (isFinishActivity && context is Activity && !context.isFinishing) {
            context.finish();
        }
    }
}